/**
 * All Rights Reserved , Copyright (C) 2020 , 青岛鼎信通讯股份有限公司
 * WorkTaskService
 * 日程任务
 * 修改纪录
 * 2020-11-02 版本：1.0 zhanglongfei 创建。
 * 
 * @version 版本：1.0
 * @author 作者：zhanglongfei
 * 创建日期：2020-11-02
 */
package com.topscomm.work.service.impl;

import java.time.Instant;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.topscomm.base.calendar.PeroidParams;
import com.topscomm.base.calendar.PeroidRepeatService;
import com.topscomm.base.pojo.BasePermissionManageEntity;
import com.topscomm.base.pojo.BaseRemindConfigEntity;
import com.topscomm.base.service.IBasePermissionManageService;
import com.topscomm.base.service.IBaseRemindConfigService;
import com.topscomm.basic.BasicEntity;
import com.topscomm.basic.exception.ServiceException;
import com.topscomm.basic.util.PrimaryKeyUtil;
import com.topscomm.basic.util.SQLAdapter;
import com.topscomm.pub.util.ConvertUtil;
import com.topscomm.pub.util.DateUtil;
import com.topscomm.pub.util.StringBufferProxy;
import com.topscomm.work.WorkSystemConst.WorkSourceAppEnum;
import com.topscomm.work.WorkSystemConst.WorkSourceTypeEnum;
import com.topscomm.work.pojo.WorkScheduleEntity;
import com.topscomm.work.pojo.WorkTaskEntity;
import com.topscomm.work.service.IWorkScheduleService;
import com.topscomm.work.service.IWorkTaskService;
import com.topscomm.work.service.impl.auto.WorkTaskServiceAuto;

import cn.hutool.core.date.DateBetween;
import cn.hutool.core.date.DateUnit;

@Service(value = "workTaskService")
@Scope(value = "singleton")
public class WorkTaskService extends WorkTaskServiceAuto implements IWorkTaskService {
	@Autowired
	private IBaseRemindConfigService baseRemindConfigService;
	@Autowired
	private IWorkScheduleService workScheduleService;
	@Autowired
	private IBasePermissionManageService basePermissionManageService;
	@Autowired
	private PeroidRepeatService peroidRepeatService;

	/**
	 * @description: 修改周期任务
	 * @param map
	 * @return
	 * @author: zhanglongfei
	 * @date: 2020年11月4日下午5:23:44
	 * @modify:
	 */
	@Override
	protected void updateBefore(Map<String, Object> paraMap) throws ServiceException {
		WorkTaskEntity taskEntity = new WorkTaskEntity();
		taskEntity.convertFromMap(paraMap);
		// 删除所有数据，重新生成
		deleteOldFatureData(taskEntity);
		List<Map<String, Object>> remindList = null;
		if (paraMap.containsKey("remindList")) {
			remindList = (List<Map<String, Object>>) paraMap.get("remindList");
			for (Map<String, Object> map : remindList) {
				map.remove("id");
			}
		}
		List<BasePermissionManageEntity> userList = workScheduleService.processSelectUsers(paraMap);
		if (remindList != null)
			baseRemindConfigService.batchSaveRemindConfigList(String.valueOf(taskEntity.getId()),
					WorkSourceTypeEnum.WorkTask, remindList);
		if (userList != null)
			basePermissionManageService.batchSaveList(String.valueOf(taskEntity.getId()), WorkSourceTypeEnum.WorkTask,
					userList);
		generatePeroidSchedule(taskEntity, remindList, userList, false);
	}

	/**
	 * @description:保存周期任务-新增
	 * @param paraMap
	 * @return
	 * @author: zhanglongfei
	 * @date: 2020年11月3日上午11:08:51
	 * @modify:
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public WorkTaskEntity saveWorkTask(Map<String, Object> paraMap, List<Map<String, Object>> remindList,
			List<BasePermissionManageEntity> userList) {
		WorkTaskEntity taskEntity = new WorkTaskEntity();
		taskEntity.convertFromMap(paraMap);
		insert(taskEntity);
		if (remindList != null)
			baseRemindConfigService.batchSaveRemindConfigList(String.valueOf(taskEntity.getId()),
					WorkSourceTypeEnum.WorkTask, remindList);
		if (userList != null)
			basePermissionManageService.batchSaveList(String.valueOf(taskEntity.getId()), WorkSourceTypeEnum.WorkTask,
					userList);
		generatePeroidSchedule(taskEntity, remindList, userList, true);
		return taskEntity;
	}

	/**
	 * @description:生成周期日程
	 * @param taskEntity
	 * @param remindList
	 * @param userList
	 * @param generateExpireData
	 *            是否生成过期数据
	 * @author: zhanglongfei
	 * @date: 2020年11月3日上午11:47:43
	 * @modify:
	 */
	private void generatePeroidSchedule(WorkTaskEntity taskEntity, List<Map<String, Object>> remindList,
			List<BasePermissionManageEntity> userList, boolean generateExpireData) {
		List<Map<String, Object>> list = queryPeriodDateList(taskEntity);
		// if (list.size() > 60) {
		// throw new MessageException("所选周期生成过多，请保持在60条以内");
		// }
		generateAllDate(list, taskEntity, remindList, userList, generateExpireData);
	}

	/**
	 * @description:生成所有数据
	 * @param timeList
	 * @param taskEntity
	 * @param remindList
	 * @param userList
	 * @param generateExpireData
	 *            是否生成过期数据
	 * @author: zhanglongfei
	 * @date: 2020年11月3日下午4:48:52
	 * @modify:
	 */
	private void generateAllDate(List<Map<String, Object>> timeList, WorkTaskEntity taskEntity,
			List<Map<String, Object>> remindList, List<BasePermissionManageEntity> userList,
			boolean generateExpireData) {
		List<BasicEntity> scheduleList = new ArrayList<>();
		List<BasicEntity> remindConfigList = new ArrayList<>();
		List<BasicEntity> permissionList = new ArrayList<>();
		Date nowDate = new Date();
		for (Map<String, Object> timeMap : timeList) {
			WorkScheduleEntity scheduleEntity = generateSchedule(timeMap, taskEntity);
			if (!generateExpireData) {
				// 过期数据不生成
				if (scheduleEntity.getEndtime().compareTo(nowDate) < 0) {
					continue;
				}
			}
			String sourceId = String.valueOf(scheduleEntity.getId());
			scheduleList.add(scheduleEntity);
			remindConfigList.addAll(generateRemindConfig(sourceId, WorkSourceTypeEnum.WorkSchedule, remindList));
			for (BasePermissionManageEntity userEntity : userList) {
				BasePermissionManageEntity newEntity = JSON.parseObject(JSON.toJSONString(userEntity),
						BasePermissionManageEntity.class);
				newEntity.setId(0);
				newEntity.setSourceid(sourceId);
				newEntity.setCreateon(new Date());
				newEntity.setModifiedon(newEntity.getCreateon());
				newEntity.setSourcetype(WorkSourceTypeEnum.WorkSchedule);
				permissionList.add(newEntity);
			}
		}
		workScheduleService.insertBatch(scheduleList);
		baseRemindConfigService.insertBatch(remindConfigList);
		basePermissionManageService.insertBatch(permissionList);
		if (scheduleList.size() > 0) {
			workScheduleService.pushRemindTask((WorkScheduleEntity) scheduleList.get(0), userList, null, false, false,
					getSessionUserBean());
		}
	}

	/**
	 * @description:生成日程数据
	 * @param timeMap
	 * @param taskEntity
	 * @return
	 * @author: zhanglongfei
	 * @date: 2020年11月3日下午4:49:05
	 * @modify:
	 */
	private WorkScheduleEntity generateSchedule(Map<String, Object> timeMap, WorkTaskEntity taskEntity) {
		DateBetween duration = DateBetween.create(taskEntity.getBegintime(), taskEntity.getEndtime());
		int times = ConvertUtil.convertToInt(duration.between(DateUnit.MS));
		String beginString = DateUtil.dateToString(taskEntity.getBegintime(), "yyyy-MM-dd HH:mm:ss");
		Date beginTime = ConvertUtil.convertToDate(timeMap.get("date").toString() + " " + beginString.split(" ")[1]);
		Date endTime = new Date(Instant.ofEpochMilli(beginTime.getTime()).plusMillis(times).toEpochMilli());
		WorkScheduleEntity entity = new WorkScheduleEntity();
		long[] arrayId = PrimaryKeyUtil.GeneIDsFromCache(entity.getTableName(), 1);
		entity.setId(arrayId[0]);
		entity.setBegintime(beginTime);
		entity.setContent(taskEntity.getContent());
		entity.setEndtime(endTime);
		entity.setHandleusercode(taskEntity.getHandleusercode());
		entity.setHandleusername(taskEntity.getHandleusername());
		entity.setName(taskEntity.getName());
		entity.setScheduletype(taskEntity.getScheduletype());
		entity.setSourceapp(WorkSourceAppEnum.Work);
		entity.setSourceid(String.valueOf(taskEntity.getId()));
		entity.setSourcetype(WorkSourceTypeEnum.WorkTask);
		entity.setTags(taskEntity.getTags());
		entity.setDescription(timeMap.get("name").toString());
		entity.setCreateon(new Date());
		entity.setModifiedon(entity.getCreateon());
		return entity;
	}

	/**
	 * @description:生成日程提醒
	 * @param sourceId
	 * @param sourceType
	 * @param remindList
	 * @return
	 * @author: zhanglongfei
	 * @date: 2020年11月3日下午4:55:02
	 * @modify:
	 */
	private List<BaseRemindConfigEntity> generateRemindConfig(String sourceId, String sourceType,
			List<Map<String, Object>> remindList) {
		List<BaseRemindConfigEntity> list = new ArrayList<>();
		for (Map<String, Object> item : remindList) {
			BaseRemindConfigEntity newEntity = new BaseRemindConfigEntity();
			newEntity.convertFromMap(item);
			newEntity.setSourceid(sourceId);
			newEntity.setSourcetype(sourceType);
			newEntity.setCreateon(new Date());
			newEntity.setModifiedon(newEntity.getCreateon());
			newEntity.setState(0);
			list.add(newEntity);
		}
		return list;
	}

	@Override
	protected void deleteBefore(String whereSql) {
		StringBufferProxy sqlBufferProxy = new StringBufferProxy();
		sqlBufferProxy.appendLineSingle(whereSql.replace("id", "sourceid").replaceAll("\\(", "('")
				.replaceAll("\\)", "')").replace("\\,", "','"));
		sqlBufferProxy.appendLineSingle(" and sourcetype='{0}'", WorkSourceTypeEnum.WorkTask);
		baseRemindConfigService.deleteByWhere(sqlBufferProxy.toString());
		basePermissionManageService.deleteByWhere(sqlBufferProxy.toString());
		// 由于schedule表的service也有级联删除，需要单独处理
		List<WorkScheduleEntity> scheduleList = workScheduleService.queryByWhere(sqlBufferProxy.toString());
		if (scheduleList.size() > 0) {
			String whereString = " id in (";
			for (WorkScheduleEntity workScheduleEntity : scheduleList) {
				whereString += "" + workScheduleEntity.getId() + ",";
			}
			whereString = whereString.substring(0, whereString.length() - 1) + ")";
			List<BasePermissionManageEntity> permissionManageList = basePermissionManageService
					.queryByWhere("sourceid = '" + scheduleList.get(0).getId() + "' and sourcetype='"
							+ WorkSourceTypeEnum.WorkSchedule + "'");
			workScheduleService.deleteByWhere(whereString);
			workScheduleService.pushRemindTask(scheduleList.get(0), permissionManageList, null, false, true,
					getSessionUserBean());
		}
	}

	/**
	 * @description:删除周期日程中，未开始的所有日程
	 * @param taskEntity
	 * @author: zhanglongfei
	 * @date: 2020年11月4日下午7:36:28
	 * @modify:
	 */
	private void deleteOldFatureData(WorkTaskEntity taskEntity) {
		StringBufferProxy sql = new StringBufferProxy();
		sql.appendLineSingle("sourcetype='{0}' and sourceid='{1}'", WorkSourceTypeEnum.WorkTask, taskEntity.getId());
		baseRemindConfigService.deleteByWhere(sql.toString());
		basePermissionManageService.deleteByWhere(sql.toString());
		sql.appendLineSingle(" and endtime>={0}", SQLAdapter.toDateLong(DateUtil.dateToString(new Date())));
		List<WorkScheduleEntity> scheduleList = workScheduleService.queryByWhere(sql.toString());
		if (scheduleList.size() > 0) {
			String whereString = " id in (";
			for (WorkScheduleEntity workScheduleEntity : scheduleList) {
				whereString += workScheduleEntity.getId() + ",";
			}
			whereString = whereString.substring(0, whereString.length() - 1) + ")";
			workScheduleService.deleteByWhere(whereString);
		}
	}

	/**
	 * @description:查询周期中的日期
	 * @param taskEntity
	 * @return
	 * @author: zhanglongfei
	 * @date: 2020年11月5日下午4:08:52
	 * @modify:
	 */
	@Override
	public List<Map<String, Object>> queryPeriodDateList(WorkTaskEntity taskEntity) {
		PeroidParams repeatParams = convertPeriodParamByTaskEntity(taskEntity);
		List<Map<String, Object>> list = peroidRepeatService.getPeroidDays(repeatParams);
		return list;
	}

	/**
	 * @description:转换周期参数
	 * @param taskEntity
	 * @return
	 * @author: zhanglongfei
	 * @date: 2020年11月4日下午5:32:20
	 * @modify:
	 */
	private PeroidParams convertPeriodParamByTaskEntity(WorkTaskEntity taskEntity) {
		PeroidParams repeatParams = new PeroidParams();
		repeatParams.setBeginTime(DateUtil.dateToString(taskEntity.getBegintime(), "yyyy-MM-dd"));
		repeatParams.setEndtype(taskEntity.getStoptype());
		if (taskEntity.getStoptype() == 1) {
			repeatParams.setEndTime(DateUtil.dateToString(taskEntity.getStoptime(), "yyyy-MM-dd"));
		} else {
			repeatParams.setTimes(taskEntity.getRepeatcount());
		}
		repeatParams.setDaySequence(taskEntity.getDaysequence());
		repeatParams.setMonthWeekTime(taskEntity.getWeeksequence());
		repeatParams.setPeriodFrequency(taskEntity.getPeriodfrequency());
		repeatParams.setPeriodType(taskEntity.getPeriodtype());
		repeatParams.setRepeatEveryType(taskEntity.getMonthrepeattype());
		return repeatParams;
	}
}
